use pom::parser::*;

use crate::import_conf::ParamType;
fn space<'a>() -> Parser<'a, char, ()> {
    one_of(" \t\r\n").repeat(0..).discard()
}
fn year<'a>() -> Parser<'a, char, u32> {
    one_of("0123456789").repeat(4).map(|s: Vec<char>| {
        let s: String = s.into_iter().collect();
        s.parse::<u32>().unwrap()
    })
}
fn one_or_two_num<'a>() -> Parser<'a, char, u32> {
    one_of("0123456789").repeat(1..3).map(|s: Vec<char>| {
        let s: String = s.into_iter().collect();
        s.parse::<u32>().unwrap()
    })
}
fn two_num<'a>() -> Parser<'a, char, u32> {
    one_of("0123456789").repeat(2).map(|s: Vec<char>| {
        let s: String = s.into_iter().collect();
        s.parse::<u32>().unwrap()
    })
}
fn year_month<'a>() -> Parser<'a, char, u32> {
    let sc1 = sym('-') | sym('/') | sym('年') | sym('.');
    let sc2 = sym('-') | sym('/') | sym('月') | sym('.');
    let date = space() * (year() + two_num() + two_num().opt())
        | (year() - sc1 + one_or_two_num() - sc2 + one_or_two_num().opt()) - any().repeat(0..);
    date.map(|((year, month), _day)| year * 100 + month)
}
fn year_quarter<'a>() -> Parser<'a, char, u32> {
    let sc1 = sym('年');
    let sc2 = sym('季');
    let jd =
        (sym('一') | sym('二') | sym('三') | sym('四') | sym('1') | sym('2') | sym('3') | sym('4'))
            .map(|c| match c {
                '一' | '1' => 1u32,
                '二' | '2' => 2,
                '三' | '3' => 3,
                '四' | '4' => 4,
                _ => unreachable!(),
            });
    let date = space() * (year() - sc1 + jd - sc2) - any().repeat(0..);
    date.map(|(year, quarter)| year * 10 + quarter)
}

pub(super) fn parse_param_by_file_name(
    file_name: &str,
    date_after: &str,
    pt: ParamType,
) -> anyhow::Result<u32> {
    let mut index = 0usize;
    if !date_after.is_empty() {
        index = file_name
            .find(date_after)
            .ok_or(anyhow::anyhow!("文件名:{file_name}中没有{date_after}"))?;
        index += date_after.len();
    }
    let file_name = &file_name[index..];
    let input: Vec<char> = file_name.chars().collect();
    let val = match pt {
        ParamType::Quarter => year_quarter()
            .parse(&input)
            .or_else(|err| anyhow::bail!("文件名:{}中没有找到年份和季度；{}", file_name, err))?,
        ParamType::Month => year_month()
            .parse(&input)
            .or_else(|err| anyhow::bail!("文件名:{}中没有找到年份和月份；{}", file_name, err))?,
    };
    Ok(val)
}
